#include "Dri_ADC.h"

/**
 * @brief ADC 初始化
 *
 */
void Dri_ADC_Init(void)
{
    // 1. 时钟设置 ------------------------------------------------
    // 1.1 开启 ADC 时钟使能
    RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
    // 1.2 ADC 时钟分频设置，进行6分频，得到12MHz (RCC_CFGR.ADCPRE=10)
    RCC->CFGR |= RCC_CFGR_ADCPRE_1;
    RCC->CFGR &= ~RCC_CFGR_ADCPRE_0;


    // 2. ADC1 设置 ------------------------------------------------
    // 2.1 设置 ADC1_IN16 的采样时间为 239.5 周期 (ADC1_SMPR1.SMP10=111)
    ADC1->SMPR1 |= ADC_SMPR1_SMP16_2;
    ADC1->SMPR1 |= ADC_SMPR1_SMP16_1;
    ADC1->SMPR1 |= ADC_SMPR1_SMP16_0;
    // 2.2 设置规则组序列长度为1 (ADC1_SQR1.L=0000)
    ADC1->SQR1 &= ~ADC_SQR1_L;
    // 2.3 将 ADC1_IN16 放入规则组序列中的第一个位置 (ADC1_SQR3.SQ1=1010)
    ADC1->SQR3 &= ~ADC_SQR3_SQ1; // 将SQ1对应的4个位置0
    ADC1->SQR3 |= (16 << 0);     // 将 16 放入 SQ1 的位置上
    // 2.4 设置规则组序列不开启扫描模式 (ADC1_CR1.SCAN=0)
    ADC1->CR1 &= ~ADC_CR1_SCAN;
    // 2.5 设置规则组序列开启连续转换模式 (ADC1_CR2.CONT=1)
    ADC1->CR2 |= ADC_CR2_CONT;
    // 2.6 设置关闭规则组的外部事件触发 (ADC1_CR2.EXTTRIG=0)
    ADC1->CR2 &= ~ADC_CR2_EXTTRIG;
    // 2.7 设置规则组序列的数据寄存器对齐方式为右对齐 (ADC1_CR2.ALIGN=0)
    ADC1->CR2 &= ~ADC_CR2_ALIGN;
    // 2.8 设置开启ADC1的两个内部通道 (ADC1_CR2.TSVREFE=1)
    ADC1->CR2 |= ADC_CR2_TSVREFE;
}

/**
 * @brief ADC 启动转换
 *
 */
void Dri_ADC_Start(void)
{
    // 1. 唤醒 ADC (ADON是0的时候置1)
    ADC1->CR2 |= ADC_CR2_ADON;

    // 2. 开启校准并等待校准完成 (同时ADC稳定时间会过去)
    ADC1->CR2 |= ADC_CR2_CAL;
    while (ADC1->CR2 & ADC_CR2_CAL)
        ;

    // 3. 启动 ADC 转换（ADON是1的时候置1）
    ADC1->CR2 |= ADC_CR2_ADON;

    // 4. 等待 ADC 转换结束
    while (!(ADC1->SR & ADC_SR_EOC))
        ;
}

/**
 * @brief 返回测得的电压
 * 
 * @return float 电压值，范围为 0.0 到 3.3 伏特
 */
float Dri_ADC_GetVoltage(void)
{
    return ADC1->DR / 4095.0 * 3.3;
}

/**
 * @brief 返回测得的温度
 *
 * @return float 温度值
 */
float Dri_ADC_GetTemperature(void)
{
    // 温度(°C) = {(V25 - VSENSE) / Avg_Slope} + 25,  V25 = 1.43V, Avg_Slope = 4.3mV/°C
    // Avg_Slop 是 4.3 mv/°C， 1.43 单位是 V，需要统一单位
    return ((1.43 - Dri_ADC_GetVoltage()) * 1000) / 4.3 + 25;
}
